/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021.
 * Description: drol header file
 * Author: yanbo <joey.yanbo@huawei.com>
 * Create: 2020-11-19
 */
#ifndef DROL_H
#define DROL_H

#include <asm-generic/errno-base.h>
#include <linux/types.h>
#include <asm/io.h>
#include <linux/hal/hal_log.h>

#define REG_SIZE	4
#ifdef CONFIG_PPC32
#define do_drol_early_ioremap(x)	ioremap(x, REG_SIZE)
#define do_drol_early_iounmap(x)	iounmap(x)
#else
#include <asm/early_ioremap.h>
#define do_drol_early_ioremap(x)	early_ioremap(x, REG_SIZE)
#define do_drol_early_iounmap(x)	early_iounmap(x, REG_SIZE)
#endif

#define DROL_REG_SIZE		4
#define DROL_OP_READ		(1 << 0)
#define DROL_OP_WRITE		(1 << 1)
#define DROL_NAME_LEN		32
#define DROL_EARLY_IOREMAP	drol_early_ioremap
#define DROL_EARLY_IOUNMAP	drol_early_iounmap
#define DROL_IOREMAP		drol_ioremap
#define DROL_IOUNMAP		drol_iounmap

static inline bool addr_cells_range_ok(int cells)
{
	return cells > 0 && cells <= sizeof(phys_addr_t);
}

struct drol_op {
	phys_addr_t reg;
	void *addr;
	unsigned int reuse;
	unsigned int op;
	unsigned int clear;
	unsigned int set;
	unsigned int xor;
	unsigned int delay;
};

typedef void *(*drol_map)(phys_addr_t phys);
typedef void (*drol_unmap)(void *addr);

typedef int (*drol_get_op_func)(struct drol_op *op, int op_size, const char *name, const void *dtb_addr);

#ifdef CONFIG_RTOS_DROL

/* boot/compressed/hwdog.c will use null definition of drol_get_op */
#if defined(HWDOG_DECOMPRESS_C)
static int drol_get_op(struct drol_op *op, int op_size, const char *name, const void *dtb_addr)
{
	return 0;
}
#else
extern int drol_get_op(struct drol_op *op, int op_size, const char *name, const void *dtb_addr);
#endif

extern void drol_unmap_op(struct drol_op *op, int op_size, drol_unmap unmap);
extern int drol_map_op(struct drol_op *op, int op_size, drol_map map, drol_unmap unmap);
extern int drol_get_op_fdt(struct drol_op *op, int op_size, const char *name, const void *dtb_addr);
extern void drol_do_op(struct drol_op *op, int op_size);
extern void *drol_early_ioremap(phys_addr_t phys);
extern void drol_early_iounmap(void *virt);
extern void *drol_ioremap(phys_addr_t phys);
extern void drol_iounmap(void *virt);
extern int drol_do_op_once(const char *name, struct drol_op *op, int op_size);
extern int drol_do_customized_op_once(const char *name,
	struct drol_op *op, int op_size, u32 irq, u32 val);

#else
static inline int drol_get_op(struct drol_op *op, int op_size, const char *name, const void *dtb_addr)
{
	return 0;
}
static inline void drol_unmap_op(struct drol_op *op, int op_size, drol_unmap unmap) {}
static inline int drol_map_op(struct drol_op *op, int op_size, drol_map map, drol_unmap unmap)
{
	return 0;
}
static inline int drol_get_op_fdt(struct drol_op *op, int op_size, const char *name, const void *dtb_addr)
{
	return 0;
}
static inline void drol_do_op(struct drol_op *op, int op_size) {}
static inline void *drol_early_ioremap(phys_addr_t phys)
{
	return NULL;
}
static inline void drol_early_iounmap(void *virt) {}
static inline void *drol_ioremap(phys_addr_t phys)
{
	return NULL;
}
static inline void drol_iounmap(void *virt) {}
static inline int drol_do_op_once(const char *name, struct drol_op *op, int op_size)
{
	return 0;
}
static inline int drol_do_customized_op_once(const char *name,
	struct drol_op *op, int op_size, u32 irq, u32 val)
{
	return 0;
}
#endif

#endif
